package com.ocom.mqsubsidy.business.ConsPerReports;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ocom.common.AcpService;
import com.ocom.common.entity.master.EntityFileDownloadInfo;
import com.ocom.common.request.web.GetConsPerReportsRequest;
import com.ocom.common.resp.Result;
import com.ocom.common.utils.RandomUtil;
import com.ocom.common.utils.StringUtils;
import com.ocom.common.utils.excel.SXSSFWORKBookUtils;
import com.ocom.common.vo.simple.ConsumeDetailVo;
import com.ocom.mqsubsidy.config.ConsPerReportsConfig;
import com.ocom.mqsubsidy.feign.AccessClientService;
import com.ocom.mqsubsidy.feign.MinioClientService;
import com.ocom.mqsubsidy.feign.XfRecordFeign;
import com.rabbitmq.client.Channel;
import org.apache.commons.io.FileUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.stereotype.Component;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.Map;

@Component
public class ConsPerReportsConsumerMqListener {

    private Logger logger = LoggerFactory.getLogger(ConsPerReportsConsumerMqListener.class);



    @Autowired
    private XfRecordFeign xfRecordFeign;

    @Autowired
    AccessClientService accessClientService;

    @Value("${save.path}")
    String excelPath;

    @Autowired
    MinioClientService minioClientService;

    @RabbitListener(queues = ConsPerReportsConfig.CONSPERREPORTS_QUEUE)
    public void process(Message message, @Headers Map<String, Object> headers, Channel channel) throws Exception {
        logger.info("ConsPerReports 消费中");
        logger.info("message【{}】", message);
        String humanMessage = new String(message.getBody(), StandardCharsets.UTF_8);
        //TODO 数据库操作样例
        logger.info("ConsPerReports-start:【{}】", humanMessage);
        logger.info("System.currentTimeMillis()【{}】", System.currentTimeMillis());


        GetConsPerReportsRequest getConsPerReportsRequest = JSON.parseObject(humanMessage,GetConsPerReportsRequest.class);

        getConsPerReportsRequest.setSize(1);
        getConsPerReportsRequest.setPage(1);
        EntityFileDownloadInfo entityFileDownloadInfo=new EntityFileDownloadInfo();
        entityFileDownloadInfo.setId(getConsPerReportsRequest.getId().longValue());
        entityFileDownloadInfo.setName("人员消费汇总报表导出");

        String filePath = excelPath+ RandomUtil.getRandomString(32) +".xlsx";
        File file=new File(filePath);

        //创建一个文件
        try {
            //创建Excel文件薄
            HSSFWorkbook workbook=new HSSFWorkbook();
            //创建工作表sheeet
            workbook.createSheet();
            //判断文件或文件夹是否存在
            boolean flag = file.exists();
            if(flag)
            {
                //文件存在就要删除文件
                file.delete();
            }
            file.createNewFile();
            FileOutputStream stream= FileUtils.openOutputStream(file);
            workbook.write(stream);
            stream.close();
        }catch (Exception e){
            e.printStackTrace();
        }finally {

        }

        SXSSFWorkbook sxssfWorkbook = null;
        BufferedOutputStream outputStream = null;
        try {
            //这样表示SXSSFWorkbook只会保留100条数据在内存中，其它的数据都会写到磁盘里，这样的话占用的内存就会很少
            sxssfWorkbook = new SXSSFWorkbook(SXSSFWORKBookUtils.getXSSFWorkbook(filePath),100);
            //获取第一个Sheet页
            SXSSFSheet sheet = sxssfWorkbook.getSheetAt(0);

            if (StringUtils.isEmpty(getConsPerReportsRequest.getDeptIds())){
                getConsPerReportsRequest.setDeptIds("-1");
            }

            Result result =xfRecordFeign.getConsPerReports(getConsPerReportsRequest);

            if(result.getCode()!=200){
                throw  new RuntimeException("获取人员汇总报表导出- 获取异常");
            }

            ConsumeDetailVo mjRecords = JSON.parseObject(JSON.toJSONString(result.getData()),ConsumeDetailVo.class);

            //下载失败 无数据
            if(mjRecords.getTotal()<=0){
                //下载失败
                entityFileDownloadInfo.setStatus(2l);
                entityFileDownloadInfo.setRemark("无有效记录");
                accessClientService.UpdateFileStatus(entityFileDownloadInfo);
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
                throw new RuntimeException("无有效记录");
            }

            int a = mjRecords.getTotal();
            int b = 500;
            BigDecimal aBig = new BigDecimal(a);
            BigDecimal bBig = new BigDecimal(b);
            //向上取整
            Integer pages =   (int)Math.ceil(aBig.divide(bBig).doubleValue());

            SXSSFRow row0 = sheet.createRow(0);
            row0.createCell(0).setCellValue("日期范围");
            row0.createCell(1).setCellValue("部门");
            row0.createCell(2).setCellValue("学工号");
            row0.createCell(3).setCellValue("姓名");
            row0.createCell(4).setCellValue("卡号");
            row0.createCell(5).setCellValue("总消费金额");
            row0.createCell(6).setCellValue("总优惠金额");
            row0.createCell(7).setCellValue("总实付金额");
            row0.createCell(8).setCellValue("总消费笔数");
            row0.createCell(9).setCellValue("代扣消费金额");
            row0.createCell(10).setCellValue("代扣消费笔数");
            row0.createCell(11).setCellValue("现金钱包消费金额");
            row0.createCell(12).setCellValue("补贴钱包消费金额");
            row0.createCell(13).setCellValue("优惠券消费金额");
            row0.createCell(14).setCellValue("虚拟账户消费笔数");
            row0.createCell(15).setCellValue("记次消费金额");
            row0.createCell(16).setCellValue("记次消费笔数");

            for (int i = 0; i < pages; i++) {
                getConsPerReportsRequest.setPage(i+1);
                getConsPerReportsRequest.setSize(500);
                Result result1 =xfRecordFeign.getConsPerReports(getConsPerReportsRequest);

                ConsumeDetailVo mjRecords1 = JSON.parseObject(JSON.toJSONString(result1.getData()),ConsumeDetailVo.class);

                int  z =0;
                for (Object o:mjRecords1.getList()){

                    JSONObject jsonObject= JSON.parseObject(JSON.toJSONString(o),JSONObject.class);
                    z++;
                    SXSSFRow row = sheet.createRow(i * 500 + z);

                    row.createCell(0).setCellValue(jsonObject.getString("sTime"));
                    row.createCell(1).setCellValue(jsonObject.getString("deptName"));
                    row.createCell(2).setCellValue(jsonObject.getString("pCode"));
                    row.createCell(3).setCellValue(jsonObject.getString("pName"));
                    row.createCell(4).setCellValue(jsonObject.getString("cardNo"));
                    row.createCell(5).setCellValue(AcpService.stringAmount(jsonObject.getString("allAmount")));
                    row.createCell(6).setCellValue(AcpService.stringAmount(jsonObject.getString("allDiscount")));
                    row.createCell(7).setCellValue(AcpService.stringAmount(jsonObject.getString("allRealAmount")));
                    row.createCell(8).setCellValue(jsonObject.getString("allTimes"));
                    row.createCell(9).setCellValue(AcpService.stringAmount(jsonObject.getString("dkAmount")));
                    row.createCell(10).setCellValue(jsonObject.getString("dkTimes"));
                    row.createCell(11).setCellValue(AcpService.stringAmount(jsonObject.getString("xjAmount")));
                    row.createCell(12).setCellValue(AcpService.stringAmount(jsonObject.getString("btAmount")));
                    row.createCell(13).setCellValue(AcpService.stringAmount(jsonObject.getString("yhqAmount")));
                    row.createCell(14).setCellValue(jsonObject.getString("xnzhTimes"));
                    row.createCell(15).setCellValue(AcpService.stringAmount(jsonObject.getString("jcAmount")));
                    row.createCell(16).setCellValue(jsonObject.getString("jcTimes"));
                }
            }

            outputStream = new BufferedOutputStream(new FileOutputStream(filePath));
            sxssfWorkbook.write(outputStream);
            outputStream.flush();
            sxssfWorkbook.dispose();// 释放workbook所占用的所有windows资源
        } catch (IOException e) {
            e.printStackTrace();

            entityFileDownloadInfo.setStatus(2l);
            accessClientService.UpdateFileStatus(entityFileDownloadInfo);
//            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            return;

        }finally {
            if(outputStream!=null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        File file1=new File(filePath);
        Result result3 = minioClientService.upload(file1);
        //删除本地
        file.delete();
        if(result3.getCode()!=200){
            //更改状态 失败
            entityFileDownloadInfo.setStatus(2l);
            accessClientService.UpdateFileStatus(entityFileDownloadInfo);
        }else{
            JSONObject jsonObject1 =JSON.parseObject(JSON.toJSONString( result3.getData()));
            entityFileDownloadInfo.setStatus(1l);
            entityFileDownloadInfo.setUrl(jsonObject1.getString("imageUrl"));
            accessClientService.UpdateFileStatus(entityFileDownloadInfo);
        }
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        logger.info("getConsPerReports-end:【{}】",humanMessage);
        logger.info("System.currentTimeMillis()【{}】",System.currentTimeMillis());
    }

    /**
     * 把该监听命名为B监听
     * 监听死信队列  远程服务支付接口发送消息  该队列会接受
     * [message, headers, channel]
     * @return {@link }
     * @throws
     */
    @RabbitListener(queues =  ConsPerReportsConfig.CONSPERREPORTS_DIE_QUEUE)
    public void processForDie(Message message, @Headers Map<String, Object> headers, Channel channel) throws Exception {
        //死信队列放弃
        channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
        logger.info("人员汇总报表-死信队列放弃 ， 【{}】",message);
    }
}
